package com.cuiweiyou.happypaint.view;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import com.cuiweiyou.happypaint.ui.ShapeModel;

import java.util.ArrayList;
import java.util.List;

public class PaintView extends View {

    private OnPaintViewClickListener onPaintViewClickListener;
    private int currentSize = ConfigManager.PENCIL_SIZE_PAINT;  // 当前画笔粗细
    private String currentColor = ConfigManager.COLOR_PAINT;    // 当前画笔颜色
    private int shapeMode = ConfigManager.SHAPE_LINE;           // 绘制哪种图形。默认线条
    private String letter = "";
    private List<ShapeModel> oldShapes;  // 以前画的图形
    private ShapeModel currentShape;    // 当前在画的图形
    private boolean isDoClear = false;  // 清空画布

    public PaintView(Context context) {
        this(context, null);
    }

    public PaintView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        oldShapes = new ArrayList<>();
        currentShape = new ShapeModel(currentColor, currentSize);
        setLayerType(View.LAYER_TYPE_SOFTWARE, null); // 解决硬件加速导致的清除画布后变黑
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (isDoClear) {
            canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
            isDoClear = false;
        } else {
            drawAllShapes(canvas);
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (null != onPaintViewClickListener) {
            int i = onPaintViewClickListener.onPaintViewClick();
            if (VISIBLE == i){
                return true; // 如果有选择bar显示，那么就先gone，而不绘图
            }
        }

        int x = (int) event.getX();
        int y = (int) event.getY();

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN: {
                ShapeModel.PointModel start_point = new ShapeModel.PointModel(x, y);
                currentShape.setShapeType(shapeMode);
                currentShape.setStart_point(start_point);

                if (ConfigManager.SHAPE_TEXT == shapeMode) {
                    currentShape.setLetter(letter);
                }
                break;
            }
            case MotionEvent.ACTION_MOVE: {
                ShapeModel.PointModel point = new ShapeModel.PointModel(x, y);
                currentShape.addPoint(point);
                break;
            }
            case MotionEvent.ACTION_UP: {
                ShapeModel.PointModel e_point = new ShapeModel.PointModel(x, y);
                currentShape.addPoint(e_point);
                oldShapes.add(currentShape);
                currentShape = new ShapeModel(currentColor, currentSize);
                break;
            }
        }
        invalidate();
        return true;
    }

    private double getDistance(ShapeModel.PointModel start, ShapeModel.PointModel end) {
        return Math.sqrt(Math.pow(end.getX() - start.getX(), 2) + Math.pow(end.getY() - start.getY(), 2));
    }

    // 绘制选择的图形
    public void drawOldShapes(List<ShapeModel> list) {
        clear();
        oldShapes.addAll(list);
        list.clear();
        isDoClear = false; // invalidate太快导致来不及绘制？
        invalidate();
    }

    // 绘制全部的历史图形
    private void drawAllShapes(Canvas canvas) {
        for (int i = 0; i < oldShapes.size(); i++) {
            ShapeModel shape = oldShapes.get(i);
            drawShape(shape, canvas);
        }

        drawShape(currentShape, canvas);
    }

    // 根据类型画图
    private void drawShape(ShapeModel shape, Canvas canvas) {
        ShapeModel.PointModel start_point = shape.getStart_point();
        if (null == start_point) {
            return;
        }

        int type = shape.getShapeType();
        switch (type) {
            case ConfigManager.SHAPE_STRAIGHT_LINE: { // 直线
                drawStraightLine(canvas, shape);
                break;
            }
            case ConfigManager.SHAPE_LINE: { // 手绘曲线
                drawLine(canvas, shape);
                break;
            }
            case ConfigManager.SHAPE_ARC: {  // 圆环
                drawArc(canvas, shape, 1);
                break;
            }
            case ConfigManager.SHAPE_RECT: { // 矩形框
                drawRect(canvas, shape, 1);
                break;
            }
            case ConfigManager.SHAPE_DELTA: { // 三角框
                drawDelta(canvas, shape, 1);
                break;
            }
            case ConfigManager.SHAPE_STAR: { // 五星框
                drawStar(canvas, shape, 1);
                break;
            }
            case ConfigManager.SHAPE_ARC_FILL: {  // 圆饼
                drawArcFill(canvas, shape);
                break;
            }
            case ConfigManager.SHAPE_RECT_FILL: { // 矩形饼
                drawRectFill(canvas, shape);
                break;
            }
            case ConfigManager.SHAPE_DELTA_FILL: { // 三角饼
                drawDeltaFill(canvas, shape);
                break;
            }
            case ConfigManager.SHAPE_STAR_FILL: { // 五星饼
                drawStarFill(canvas, shape);
                break;
            }
            case ConfigManager.SHAPE_TEXT: {     // 文字
                drawText(canvas, shape);
                break;
            }
        }

    }

    // 画文字
    private void drawText(Canvas canvas, ShapeModel shape) {
        ShapeModel.PointModel start_point = shape.getStart_point();
        float x = start_point.getX();
        float y = start_point.getY();

        List<ShapeModel.PointModel> pointList = shape.getPointList();
        int size = pointList.size();
        if (size < 2) {
            return;
        }

        ShapeModel.PointModel point = pointList.get(size - 1);
        float x1 = point.getX();
        float y1 = point.getY();

        float dy = Math.abs(y1 - y);

        double distance = getDistance(start_point, point);

        String letter = shape.getLetter();

        Paint paint = shape.getPaint();
        paint.setTextAlign(Paint.Align.LEFT);
        paint.setTextSize((float) distance);

        if (y > y1) {
            canvas.drawText(letter, x, y, paint);
        } else {
            canvas.drawText(letter, x, y + dy, paint);
        }
    }

    // 画直线
    private void drawStraightLine(Canvas canvas, ShapeModel shape) {
        ShapeModel.PointModel start_point = shape.getStart_point();
        float x = start_point.getX();
        float y = start_point.getY();

        List<ShapeModel.PointModel> pointList = shape.getPointList();
        int size = pointList.size();
        if (size < 2) {
            return;
        }

        ShapeModel.PointModel point = pointList.get(size - 1);
        float x1 = point.getX();
        float y1 = point.getY();

        Path path = new Path();
        path.moveTo(x, y);
        path.lineTo(x1, y1);

        Paint paint = shape.getPaint();
        canvas.drawPath(path, paint);
    }

    // 画手绘曲线
    private void drawLine(Canvas canvas, ShapeModel shape) {
        ShapeModel.PointModel start_point = shape.getStart_point();
        float x = start_point.getX();
        float y = start_point.getY();
        Path path = new Path();
        path.moveTo(x, y);
        List<ShapeModel.PointModel> pointList = shape.getPointList();
        for (int j = 0; j < pointList.size(); j++) {
            ShapeModel.PointModel point = pointList.get(j);
            float x1 = point.getX();
            float y1 = point.getY();
            path.lineTo(x1, y1);
        }
        Paint paint = shape.getPaint();
        canvas.drawPath(path, paint);
    }

    // 画圆饼
    private void drawArcFill(Canvas canvas, ShapeModel shape) {
        drawArc(canvas, shape, 0);
    }

    // 画圆环
    // style:0填充，1空心
    private void drawArc(Canvas canvas, ShapeModel shape, int style) {
        ShapeModel.PointModel point_s = shape.getStart_point();
        float centre_x = point_s.getX(); // 手指按下的位置
        float centre_y = point_s.getY();

        List<ShapeModel.PointModel> pointList = shape.getPointList();
        if (pointList.size() < 1) {
            return;
        }
        ShapeModel.PointModel point = pointList.get(pointList.size() - 1);
        float x = point.getX(); // 手指滑动，最后拿起的位置
        float y = point.getY();

        float a = x - centre_x;
        float b = y - centre_y;

        float c = (float) Math.hypot(a, b); // 圆心所在斜边的长度

        /*
         * 。--------- 手指按下的位置
         * |\        |
         * | \  - -  |
         * |  /    \ |
         * |/  \    \|
         * |    .    | 点是圆心
         * |\    \  /|
         * | \    \/ |
         * |   _ _/  |
         * |        \|
         * |---------。手指滑动，最后拿起的位置
         */

        Paint paint = shape.getPaint();
        if (0 == style) {
            paint.setStyle(Paint.Style.FILL_AND_STROKE);
        } else {
            paint.setStyle(Paint.Style.STROKE);
        }

        //圆心x、圆心y、半径、画笔。这里原的原点在按下的位置。
        canvas.drawCircle(centre_x + a / 2, centre_y + b / 2, c / 2, paint);
    }

    // 画矩形饼
    private void drawRectFill(Canvas canvas, ShapeModel shape) {
        drawRect(canvas, shape, 0);
    }

    // 画矩形框
    // style:0填充，1空心
    private void drawRect(Canvas canvas, ShapeModel shape, int style) {
        ShapeModel.PointModel point_s = shape.getStart_point();
        float left = point_s.getX();
        float top = point_s.getY();

        List<ShapeModel.PointModel> pointList = shape.getPointList();
        if (pointList.size() < 1) {
            return;
        }
        ShapeModel.PointModel point = pointList.get(pointList.size() - 1);
        float right = point.getX();
        float bottom = point.getY();

        Paint paint = shape.getPaint();
        if (0 == style) {
            paint.setStyle(Paint.Style.FILL_AND_STROKE);
        } else {
            paint.setStyle(Paint.Style.STROKE);
        }

        // 左边，上边，右边，下边
        canvas.drawRect(left, top, right, bottom, paint);
    }

    // 画三角形饼
    private void drawDeltaFill(Canvas canvas, ShapeModel shape) {
        drawDelta(canvas, shape, 0);
    }

    // 画三角形框
    // style:0填充，1空心
    private void drawDelta(Canvas canvas, ShapeModel shape, int style) {
        ShapeModel.PointModel point_s = shape.getStart_point();
        float vertex_x = point_s.getX(); // 顶点
        float vertex_y = point_s.getY();

        List<ShapeModel.PointModel> pointList = shape.getPointList();
        if (pointList.size() < 1) {
            return;
        }
        ShapeModel.PointModel point = pointList.get(pointList.size() - 1);
        float bottom_center_x = point.getX(); // 底边中点
        float bottom_center_y = point.getY();

        double diffy = bottom_center_y - vertex_y;
        float a = (float) Math.sqrt(Math.pow(diffy, 2) / 3.0); // 底边

        float point_left_x = vertex_x - a;
        float point_left_y = bottom_center_y;
        float point_right_x = vertex_x + a;
        float point_right_y = bottom_center_y;
        /*
         *    。    顶点。手指按下的位置
         *   /|\
         *  / | \
         * /  |  \
         *.---。---.  底边中点。手指滑动最终放开的位置
         */

        Paint paint = shape.getPaint();
        if (0 == style) {
            paint.setStyle(Paint.Style.FILL_AND_STROKE);
        } else {
            paint.setStyle(Paint.Style.STROKE);
        }

        Path path = new Path();
        path.moveTo(vertex_x, vertex_y);
        path.lineTo(point_left_x, point_left_y);
        path.lineTo(point_right_x, point_right_y);
        path.close();

        canvas.drawPath(path, paint);
    }

    // 画五角星饼
    private void drawStarFill(Canvas canvas, ShapeModel shape) {
        drawStar(canvas, shape, 0);
    }

    // 画五角星框
    // style:0填充，1空心
    private void drawStar(Canvas canvas, ShapeModel shape, int style) {
        ShapeModel.PointModel point_s = shape.getStart_point();
        float centre_x = point_s.getX(); // 手指按下的位置
        float centre_y = point_s.getY();

        List<ShapeModel.PointModel> pointList = shape.getPointList();
        if (pointList.size() < 1) {
            return;
        }
        ShapeModel.PointModel point = pointList.get(pointList.size() - 1);
        float x = point.getX(); // 手指滑动，最后拿起的位置
        float y = point.getY();

        float a = x - centre_x;
        float b = y - centre_y;
        float c = (float) Math.hypot(a, b); // 圆心所在斜边的长度

        float cx = centre_x + a / 2;
        float cy = centre_y + b / 2;
        float radius = c / 2;

        List<ShapeModel.PointModel> pl = new ArrayList<>();
        for (int i = 270; i >= -22; i -= 72) {
            int p_x = (int) (cx + radius * Math.cos(Math.toRadians(i)));
            int p_y = (int) (cy + radius * Math.sin(Math.toRadians(i)));

            ShapeModel.PointModel pointBean = new ShapeModel.PointModel(p_x, p_y);
            pl.add(pointBean);
        }
        ShapeModel.PointModel p1 = pl.get(1);
        ShapeModel.PointModel p4 = pl.get(4);
        ShapeModel.PointModel p2 = pl.get(2);
        ShapeModel.PointModel p0 = pl.get(0);
        ShapeModel.PointModel p3 = pl.get(3);
        Path path = new Path();
        path.moveTo(p1.getX(), p1.getY());
        path.lineTo(p4.getX(), p4.getY());
        path.lineTo(p2.getX(), p2.getY());
        path.lineTo(p0.getX(), p0.getY());
        path.lineTo(p3.getX(), p3.getY());
        path.close();

        Paint paint = shape.getPaint();
        if (0 == style) {
            paint.setStyle(Paint.Style.FILL_AND_STROKE);
        } else {
            paint.setStyle(Paint.Style.STROKE);
        }

        canvas.drawPath(path, paint);
    }

    // 画笔颜色
    public void setColor(String color) {
        currentColor = color;
        currentShape.setCurrentColor(color);
    }

    // 画笔粗细
    public void setSize(int size) {
        currentSize = size;
        currentShape.setCurrentSize(size);
    }

    // 设置画布按下事件
    public void setOnPaintViewClickListener(OnPaintViewClickListener listener) {
        this.onPaintViewClickListener = listener;
    }

    // 绘制图形类型
    public void drawShape(int shape) {
        shapeMode = shape;
        letter = "";
    }

    // 绘制文字
    public void drawTextShape(String text) {
        shapeMode = ConfigManager.SHAPE_TEXT;
        letter = text;
    }

    // 清空画布
    public void clear() {
        isDoClear = true;
        oldShapes.clear();
        oldShapes = new ArrayList<>();
        currentShape = new ShapeModel(currentColor, currentSize);
        invalidate();
    }

    // 回退1步
    public void back() {
        int size = oldShapes.size();
        if (size > 0) {
            oldShapes.remove(size - 1);
        }
        invalidate();
    }

    // 本次绘图
    public List<ShapeModel> getShapes() {
        return oldShapes;
    }

    // 画图转bitmap
    public Bitmap getBitmap() {
        int w = getWidth();
        int h = getHeight();
        Bitmap bmp = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bmp);
        canvas.drawColor(Color.WHITE); /** 如果不设置canvas画布为白色，则生成透明 */
        layout(0, 0, w, h);
        draw(canvas);

        // Bitmap dst = Bitmap.createScaledBitmap(bmp, 90, 70, false); // 压缩
        // bmp.recycle(); // 释放Bitmap的native像素数组

        return bmp;
    }

    public interface OnPaintViewClickListener {
        int onPaintViewClick();
    }
}

//    PointModel point_s;
//    float left = point_s.getX();
//    float top = point_s.getY();
//
//    PointModel point;
//    float right = point.getX();
//    float bottom = point.getY();
//
//    double dx = left - right;
//    double dy = top - bottom;
//    double distance = Math.sqrt(dx * dx + dy * dy);
//    double tan = dy / dx;           // 斜率
//    double radian = Math.atan(tan); // 弧度0 - pi/2, 不是0到90°
//    double angle = Math.toDegrees(radian); // 角度